package com.googlecode.dgwt.client.dijit.base.manager;

import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style;
import com.google.gwt.user.client.ui.UIObject;
import com.googlecode.dgwt.client.dijit.Widget;
import com.googlecode.dgwt.client.dijit.base.HasScrollBars.ScrollBarVisibility;
import com.googlecode.dgwt.client.dojo.Dojo;

/**
 * @author wellsantos@wellsantos.com
 * @since 0.01
 */
public class ScrollManager {

    private static ScrollManager manager;
    
    protected ScrollManager(){
    }
    
    public static ScrollManager get() {
        if (manager == null){
            manager = new ScrollManager();
        }
        return manager;
    }

    public Element getScrollableElement(Widget widget){
        return widget.getAttachedElement("scrollableElement");
    }

    /**
     * Ensures that the specified item is visible, by adjusting the panel's scroll
     * position.
     * 
     * @param item the item whose visibility is to be ensured
     */
    public void ensureVisibility(Widget widget, UIObject item) {
        Element scroll = getScrollableElement(widget);
        Element element = item.getElement();
        Dojo.ensureVerticalVisibility(scroll, element, true);
        //FIXME horizontal visibility
    }
    
    /**
     * Gets the horizontal scroll position.
     * 
     * @return the horizontal scroll position, in pixels
     */
    public int getHorizontalScrollPosition(Widget widget) {
        return getScrollableElement(widget).getPropertyInt("scrollLeft");
    }
    
    /**
     * Gets the vertical scroll position.
     * 
     * @return the vertical scroll position, in pixels
     */
    public int getVerticalScrollPosition(Widget widget) {
        return getScrollableElement(widget).getPropertyInt("scrollTop");
    }
    
    /**
     * Scroll to the bottom of this panel.
     */
    public void scrollToBottom(Widget widget) {
        setVerticalScrollPosition(widget, getScrollableElement(widget).getPropertyInt("scrollHeight"));
    }
    
    /**
     * Scroll to the far left of this panel.
     */
    public void scrollToLeft(Widget widget) {
        setHorizontalScrollPosition(widget, 0);
    }
    
    /**
     * Scroll to the far right of this panel.
     */
    public void scrollToRight(Widget widget) {
        setHorizontalScrollPosition(widget, getScrollableElement(widget).getPropertyInt("scrollWidth"));
    }
    
    /**
     * Scroll to the top of this panel.
     */
    public void scrollToTop(Widget widget) {
        setVerticalScrollPosition(widget, 0);
    }
    
    /**
     * Sets the horizontal scroll position.
     * 
     * @param position the new horizontal scroll position, in pixels
     */
    public void setHorizontalScrollPosition(Widget widget, int position) {
        getScrollableElement(widget).setPropertyInt("scrollLeft", position);
    }

    /**
     * Sets the vertical scroll position.
     * 
     * @param position the new vertical scroll position, in pixels
     */
    public void setVerticalScrollPosition(Widget widget, int position) {
        getScrollableElement(widget).setPropertyInt("scrollTop", position);
    }

    /**
     * Sets the visibility of the horizontal scroll bar for this widget.
     * 
     * @param visibility the scroll bar visibility
     */
    public void setHorizontalScrollBar(Widget widget, ScrollBarVisibility visibility){
        setScrollBars(widget, getVerticalScrollBar(widget), visibility);
    }

    /**
     * Gets the visibility of the horizontal scroll bar for this widget.
     * 
     * @return the scroll bar visibility
     */
    public ScrollBarVisibility getHorizontalScrollBar(Widget widget){
        Element element = getScrollableElement(widget);
        String overflowValue = Dojo.getStyle(element, "overflowX");
        ScrollBarVisibility visibility = ScrollBarVisibility.parse(overflowValue);

        if (visibility == null){
            // no matches found, try to preview
            
            if (overflowValue != null 
                    && !overflowValue.trim().isEmpty()){
                return ScrollBarVisibility.AUTO;
            }
            
            overflowValue = Dojo.getStyle(element, "overflow");
            visibility = ScrollBarVisibility.parse(overflowValue);
            
            if (visibility == null 
                    && overflowValue != null 
                    && !overflowValue.trim().isEmpty()){
                return ScrollBarVisibility.AUTO;
            }
            
        }
        return visibility;
    }
    
    /**
     * Sets the visibility of the vertical scroll bar for this widget.
     * 
     * @param visibility the scroll bar visibility
     */
    public void setVerticalScrollBar(Widget widget, ScrollBarVisibility visibility){
        setScrollBars(widget, visibility, getHorizontalScrollBar(widget));
    }

    /**
     * Gets the visibility of the vertical scroll bar for this widget.
     * 
     * @return the scroll bar visibility
     */
    public ScrollBarVisibility getVerticalScrollBar(Widget widget){
        Element element = getScrollableElement(widget);
        String overflowValue = Dojo.getStyle(element, "overflowY");
        ScrollBarVisibility visibility = ScrollBarVisibility.parse(overflowValue);

        if (visibility == null){
            // no matches found, try to preview
            
            if (overflowValue != null 
                    && !overflowValue.trim().isEmpty()){
                return ScrollBarVisibility.AUTO;
            }
            
            overflowValue = Dojo.getStyle(element, "overflow");
            visibility = ScrollBarVisibility.parse(overflowValue);
            
            if (visibility == null 
                    && overflowValue != null 
                    && !overflowValue.trim().isEmpty()){
                return ScrollBarVisibility.AUTO;
            }
            
        }
        return visibility;
    }
    
    public void setScrollBars(Widget widget, ScrollBarVisibility vertical, ScrollBarVisibility horizontal){
        Style style = getScrollableElement(widget).getStyle();
        style.setProperty("overflow", "");
        setScrollBarAux(style, "overflowY", vertical);
        setScrollBarAux(style, "overflowX", horizontal);
    }

    private void setScrollBarAux(Style style, String property, ScrollBarVisibility visibility){
        if (visibility == null){
            style.setProperty(property, "");
        } else {
            style.setProperty(property, visibility.getOverflowValue());
        }
    }
    
}
